/*
 *  mfSoundPlayer.mm
 *  Mobile Frameworks
 *
 *  Created by Zach Gage on 9/6/08.
 *  Copyright 2008 stfj. All rights reserved.
 *
 */

#import "mfSoundPlayer.h"

#import "SoundEngine.h"

bool SoundEngineInitialized = false;

UInt32	numSounds;


mfSoundPlayer::mfSoundPlayer()
{
	volume = 1.0f;
	pitch = 0.0f;
	pan = 1.0f;
	stopped=true;
	
	
	mfSoundPlayer::initializeSoundEngine();
	
}

mfSoundPlayer::~mfSoundPlayer()
{
	
}

//--------------------

void mfSoundPlayer::loadSound(string fileName)
{
	if(SoundEngineInitialized)
	{
		
		myId = mfSoundGetNextID(); //get the next ID to assosciate to a sound... 
		/*right now it wont remove old ID's, so once an ID is used its gone.. this should be fixed maybe?
		it wont really effect anything, its just used as a reference name for the sound, so as long as people
		dont load and unload thousands of sounds it should be fine...*/
		
		int dotPosition = fileName.rfind(".");
		
		string fn = fileName.substr(0,dotPosition); //split the function up into fileName and fileExtension
		string fe = fileName.substr(dotPosition+1);
		
		NSString * NSFN = [[NSString alloc] initWithCString: fn.c_str()]; //get NSStrings out of the std::strings
		NSString * NSFE = [[NSString alloc] initWithCString: fe.c_str()];
		
		NSBundle* bundle = [NSBundle mainBundle]; //get the bundle location where the sounds are
		
		SoundEngine_LoadEffect([[bundle pathForResource:NSFN ofType:NSFE] UTF8String], &myId); //load em!
		
		[NSFN release]; //clear the memory
		[NSFE release];
	}
	else
	{
		mfSoundPlayer::initializeSoundEngine();
	}
}

//--------------------

void mfSoundPlayer::loadLoopingSound(string fileName)
{
	if(SoundEngineInitialized)
	{
		
		myId = mfSoundGetNextID(); 
		
		int dotPosition = fileName.rfind(".");
		
		string fn = fileName.substr(0,dotPosition); //split the function up into fileName and fileExtension
		string fe = fileName.substr(dotPosition+1);
		
		NSString * NSFN = [[NSString alloc] initWithCString: fn.c_str()]; //get NSStrings out of the std::strings
		NSString * NSFE = [[NSString alloc] initWithCString: fe.c_str()];
		
		NSBundle* bundle = [NSBundle mainBundle]; //get the bundle location where the sounds are
		
		SoundEngine_LoadLoopingEffect([[bundle pathForResource:NSFN ofType:NSFE] UTF8String], NULL, NULL, &myId); //load em!
		
		[NSFN release]; //clear the memory
		[NSFE release];
	}
	else
	{
		mfSoundPlayer::initializeSoundEngine();
	}
}

//--------------------

void mfSoundPlayer::loadLoopingSound(string loopingFileName, string attackFileName, string decayFileName)
{
	if(SoundEngineInitialized)
	{
		
		myId = mfSoundGetNextID(); 
		
		int dotPosition = loopingFileName.rfind(".");
		
		string fn = loopingFileName.substr(0,dotPosition); //split the function up into fileName and fileExtension
		string fe = loopingFileName.substr(dotPosition+1);
		
		NSString * NSFN = [[NSString alloc] initWithCString: fn.c_str()]; //get NSStrings out of the std::strings
		NSString * NSFE = [[NSString alloc] initWithCString: fe.c_str()];
		
		
		dotPosition = attackFileName.rfind(".");
		
		string fnA = attackFileName.substr(0,dotPosition); //split the function up into fileName and fileExtension
		string feA = attackFileName.substr(dotPosition+1);
		
		NSString * NSFNA = [[NSString alloc] initWithCString: fnA.c_str()]; //get NSStrings out of the std::strings
		NSString * NSFEA = [[NSString alloc] initWithCString: feA.c_str()];
		
		
		dotPosition = decayFileName.rfind(".");
		
		string fnD = decayFileName.substr(0,dotPosition); //split the function up into fileName and fileExtension
		string feD = decayFileName.substr(dotPosition+1);
		
		NSString * NSFND = [[NSString alloc] initWithCString: fnD.c_str()]; //get NSStrings out of the std::strings
		NSString * NSFED = [[NSString alloc] initWithCString: feD.c_str()];
		
		NSBundle* bundle = [NSBundle mainBundle]; //get the bundle location where the sounds are
		
		SoundEngine_LoadLoopingEffect([[bundle pathForResource:NSFN ofType:NSFE] UTF8String], 
									  [[bundle pathForResource:NSFNA ofType:NSFEA] UTF8String], 
									  [[bundle pathForResource:NSFND ofType:NSFED] UTF8String],
									  &myId); //load em!
		
		[NSFN release]; //clear the memory
		[NSFE release];
		[NSFNA release];
		[NSFEA release];
		[NSFND release];
		[NSFED release];
	}
	else
	{
		mfSoundPlayer::initializeSoundEngine();
	}
}

//--------------------

void mfSoundPlayer::unloadSound()
{
	SoundEngine_UnloadEffect(myId);
}

//--------------------

void mfSoundPlayer::play()
{
	SoundEngine_StartEffect(myId);
	stopped = false;
}

//--------------------

void mfSoundPlayer::stop()
{
	SoundEngine_StopEffect(myId, false);
	stopped = true;
}

//--------------------

void mfSoundPlayer::stopWithDecay()
{
	SoundEngine_StopEffect(myId, true);
	stopped = true;
}

//--------------------

void mfSoundPlayer::vibrate()
{
	SoundEngine_Vibrate();
}

//--------------------

void mfSoundPlayer::setVolume(float _vol)
{
	volume = _vol;
	SoundEngine_SetEffectLevel(myId, (Float32)volume);
}

//--------------------

void mfSoundPlayer::setPan(float _pan) // this is totally legacy and shouldn't really be used. SetLocation is much better
{
	//also this could be confusing. In oF pan is between 0 and 1.0 with .5 as the center. in mF it is between -1.0 and 1.0.
	//i compensate for it here and in getPan, but im not sure if thats the best strategy. I guess it's ok as long as you don't
	//use setPan and setLocation in the same program
	_pan = _pan*2 - 1.0f;
	setLocation(_pan, 0, 0);
}

//--------------------

void mfSoundPlayer::setPitch(float _pitch)
{
	pitch = _pitch;
	SoundEngine_SetEffectPitch(myId, (Float32)pitch);
}

//--------------------
/*
void mfSoundPlayer::setMultiPlay(bool _multiPlay) //within the SoundEngine class I couldn't find a way to do this...
{
	//to do
}

//--------------------

void mfSoundPlayer::setPosition(float pct)
{
	//to do
}
*/
//--------------------

void mfSoundPlayer::setLocation(float x, float y, float z)
{
	pan = (x+1.0)/2; // this is where im compensating for the scale of oF... (pan in oF is 0-1.0, in mF it's -1.0 to 1.0)
	SoundEngine_SetEffectPosition(myId, x, y, z);
}

//---------------------------------------
// this should only be called once
void mfSoundPlayer::initializeSoundEngine(){
	if(!SoundEngineInitialized){
		
		OSStatus err = SoundEngine_Initialize(44100);
		
		if(err)
		{
			printf("ERROR failed to initialize soundEngine.");
		}
		else
		{
			printf("SoundEngine initialized \n");
			numSounds=0;
			SoundEngineInitialized = true;
			OSStatus err = SoundEngine_SetListenerPosition(0.0f, 0.0f, 0.0f);
			if(err)
			{
				printf("ERROR failed to set listener position..\n (if you are running in the simulator, this is normal, sounds won't work.) \n");
			}
		}
	}
}


//---------------------------------------
void mfSoundPlayer::closeSoundEngine(){
	if(SoundEngineInitialized){
		
		SoundEngine_Teardown();
		numSounds++;
		
		SoundEngineInitialized = false;
	}
}

float mfSoundPlayer::getPitch()
{
	return pitch;
}

//---------------------------------------

float mfSoundPlayer::getPan()
{
	return pan;
}

//---------------------------------------
void ofSoundStopAll(){
	mfSoundPlayer::initializeSoundEngine();
	
	//to do stop all sounds
}

//--------------------
void ofSoundSetVolume(float vol){
	mfSoundPlayer::initializeSoundEngine();
	
	SoundEngine_SetMasterVolume((Float32)vol);
}

//--------------------
float * ofSoundGetSpectrum(int nBands){
	
	mfSoundPlayer::initializeSoundEngine();
	
	float x = 0;
	return &x; 
}

//--------------------
void mfSoundPlayer::mfSoundSetListenerLocation(float x, float y, float z){
	mfSoundPlayer::initializeSoundEngine();
	
	SoundEngine_SetListenerPosition(x, y, z);
}

//--------------------

void mfSoundPlayer::mfSoundSetListenerGain(float gain)
{
	SoundEngine_SetListenerGain(gain);
}

//--------------------

void mfSoundPlayer::mfSoundSetReferenceDistance(float dist)
{
	SoundEngine_SetReferenceDistance(dist);
}

//--------------------

void mfSoundPlayer::mfSoundSetMaxDistance(float dist)
{
	SoundEngine_SetMaxDistance(dist);
}

//--------------------

UInt32 mfSoundPlayer::mfSoundGetNextID()
{
	return numSounds++;
}

//--------------------

void mfSoundPlayer::loadBackgroundMusic(string fileName, bool queue, bool loadAtOnce)
{
	if(SoundEngineInitialized)
	{
		
		int dotPosition = fileName.rfind(".");
		
		string fn = fileName.substr(0,dotPosition); //split the function up into fileName and fileExtension
		string fe = fileName.substr(dotPosition+1);
		
		NSString * NSFN = [[NSString alloc] initWithCString: fn.c_str()]; //get NSStrings out of the std::strings
		NSString * NSFE = [[NSString alloc] initWithCString: fe.c_str()];
		
		NSBundle* bundle = [NSBundle mainBundle]; //get the bundle location where the sounds are
		
		SoundEngine_LoadBackgroundMusicTrack([[bundle pathForResource:NSFN ofType:NSFE] UTF8String], queue, loadAtOnce);
		
		[NSFN release]; //clear the memory
		[NSFE release];
	}
	else
	{
		mfSoundPlayer::initializeSoundEngine();
	}
	
}

//--------------------

void mfSoundPlayer::unloadAllBackgroundMusic()
{
	SoundEngine_UnloadBackgroundMusicTrack();
}

//--------------------

void mfSoundPlayer::startBackgroundMusic()
{
	SoundEngine_StartBackgroundMusic();
}

//--------------------

void mfSoundPlayer::stopBackgroundMusic(bool stopNow)
{
	SoundEngine_StopBackgroundMusic(!stopNow); //this is confusing but i think stopNow makes more sense than stopAtEnd in terms of how people will likely be calling this
}

//--------------------

void mfSoundPlayer::setBackgroundMusicVolume(float bgVol)
{
	SoundEngine_SetBackgroundMusicVolume((Float32)bgVol);
}